package com.miku.blog.service.impl;

import com.miku.blog.domain.*;
import com.miku.blog.domain.bo.WebsiteConfigBO;
import com.miku.blog.domain.dto.WebsiteConfigDTO;
import com.miku.blog.domain.dto.WebsitePageDTO;
import com.miku.blog.domain.param.WebsiteConfigParam;
import com.miku.blog.domain.pojo.ResponseResult;
import com.miku.blog.domain.pojo.SystemConstance;
import com.miku.blog.eume.HttpStatusEnum;
import com.miku.blog.exception.SystemException;
import com.miku.blog.service.*;
import com.miku.blog.utils.BeanCopyUtils;
import com.miku.blog.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author shkstart
 * @create ${}YEAR-06-08 8:50
 */
@Service
public class WebSiteConfigServiceImpl implements WebSiteConfigService {

    @Autowired
    private ArticleService articleService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private TagService tagService;
    @Autowired
    private UniqueViewService uniqueViewService;
    @Autowired
    private WebsitePageService websitePageService;
    @Autowired
    private WebsiteService websiteService;
    @Autowired
    private WebsiteInfoService websiteInfoService;
    @Autowired
    private WebsiteResService websiteResService;
    @Autowired
    private SocialService socialService;
    @Autowired
    private SocialLoginService socialLoginService;
    @Autowired
    private RedisCache redisCache;


    @Override
    public ResponseResult getWebSiteConfigInfo() {
        long articleCount = articleService.getArticleCount();
        long categoryCount = categoryService.count();
        long tagCount = tagService.count();
        Integer uniqueViewCount = 0;
        List<UniqueView> uniqueViewList = uniqueViewService.list();
        for (UniqueView uniqueView : uniqueViewList) {
            uniqueViewCount += uniqueView.getViewsCount();
        }

        List<WebsitePage> pageList = websitePageService.getWebSitePageList(SystemConstance.WEBSITE_ID);
        List<WebsitePageDTO> websitePageDTOS = BeanCopyUtils.copyListByType(pageList, WebsitePageDTO.class);
        WebsiteConfigDTO websiteConfigDTO = new WebsiteConfigDTO();
        websiteConfigDTO.setArticleCount((int) articleCount)
                .setCategoryCount((int) categoryCount)
                .setTagCount((int) tagCount)
                .setViewsCount(uniqueViewCount.toString())
                .setPageList(websitePageDTOS)
                .setWebsiteConfig(getWebSiteConfigBO());
        return ResponseResult.ok().setData(websiteConfigDTO);
    }




    @Override
    public ResponseResult getWebSiteConfigInformation(){
        return ResponseResult.ok().setData(getWebSiteConfigBO());
    }


    private WebsiteConfigBO getWebSiteConfigBO(){
        Website webSite = websiteService.getWebSite();
        WebsiteInfo webSiteInfo = websiteInfoService.getWebSiteInfo(webSite.getId());
        WebsiteRes webSiteRes = websiteResService.getWebSiteRes(webSite.getId());
        List<Social> socialList = socialService.getSocialList(webSite.getId());
        List<SocialLogin> socialLoginList = socialLoginService.getSocialLogin(webSite.getId());

        WebsiteConfigBO websiteConfigBO = new WebsiteConfigBO();
        BeanCopyUtils.copyProperties(websiteConfigBO, webSiteInfo, webSiteRes, webSite);

        List<String> socialTypeList = new ArrayList<>();
        socialList.stream()
                .peek(social -> {
                    String socialType = social.getSocialType();
                    for (String type : SystemConstance.SOCIAL_TYPE) {
                        if (type.equals(socialType)) {
                            try {
                                Field field = websiteConfigBO.getClass().getDeclaredField(socialType);
                                field.setAccessible(true);
                                field.set(websiteConfigBO, social.getSocialUrl());
                            } catch (NoSuchFieldException | IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    socialTypeList.add(socialType);
                }).collect(Collectors.toList());

        List<String> loginTypeList
                = socialLoginList.stream()
                .map(SocialLogin::getLoginType)
                .collect(Collectors.toList());

        websiteConfigBO.setSocialUrlList(socialTypeList)
                .setSocialLoginList(loginTypeList);
        return websiteConfigBO;
    }



    @Transactional
    @Override
    public ResponseResult updateWebsiteConfigInfo(WebsiteConfigParam websiteConfigParam) {
        WebsiteInfo websiteInfo = websiteConfigParam.getWebsiteInfo();
        List<SocialLogin> socialLoginList = websiteConfigParam.getSocialLoginList();
        if (Objects.isNull(websiteInfo) || Objects.isNull(socialLoginList)){
            return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
        }
        if (!websiteInfoService.updateWebsiteInfo(websiteInfo)) {
            throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
        }
        socialLoginList.stream()
                .peek(socialLogin -> {
                    if (!socialLoginService.updateSocialLogin(socialLogin)) {
                        throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
                    }
                })
                .collect(Collectors.toList());

        return ResponseResult.ok();
    }

    @Transactional
    @Override
    public ResponseResult updateWebsiteConfigRes(WebsiteConfigParam websiteConfigParam) {
        Website website = websiteConfigParam.getWebsite();
        WebsiteRes websiteRes = websiteConfigParam.getWebsiteRes();
        String websocketUrl = websiteConfigParam.getWebsocketUrl();
        if (Objects.isNull(website) || Objects.isNull(websiteRes) || Objects.isNull(websocketUrl)){
            return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
        }
        if (!websiteService.updateWebsite(website)
                || !websiteResService.updateWebsiteRes(websiteRes)
                || !websiteInfoService.updateWebsocketUrl(websocketUrl))
        {
            throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
        }

        updateRedisByWebsite(website);

        return ResponseResult.ok();
    }

    @Transactional
    @Override
    public ResponseResult updateSocial(List<Social> socials) {
        socials.stream()
                .peek(social -> {
                    if(!socialService.updateSocial(social)){
                        throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
                    }
                }).collect(Collectors.toList());
        return ResponseResult.ok();
    }


    private void updateRedisByWebsite(Website website){

        redisCache.setCacheHashMap(SystemConstance.REDIS_WEBSITE_CONFIG_REVIEW_HASH_KEY,
                SystemConstance.REDIS_WEBSITE_IS_COMMENT_REVIEW_KEY,
                website.getIsCommentReview());

        redisCache.setCacheHashMap(SystemConstance.REDIS_WEBSITE_CONFIG_REVIEW_HASH_KEY,
                SystemConstance.REDIS_WEBSITE_IS_MESSAGE_REVIEW_KEY,
                website.getIsMessageReview());
    }
}
